/**
 * 计算器控件，虚拟光标实现，虚拟光标可以裸露在最外层，还可以嵌套在If层
 * If可以为一个嵌套对象
 */

import {deepFullCopy, messages} from "share/common";
import React from 'react'
import { Modal, Row, Col, Tabs, Tree, Tag, Input, message, Spin, Button } from 'antd'
const { TabPane } = Tabs;
import ReactDOM from 'react-dom';
import 'styles/financial-account/calculator-modal.scss';
import credentialService from "containers/financial-account/credential-definition/credential-definition-service";
import constants from 'share/constants';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import Condition from "components/condition";
const { TreeNode } = Tree;
const If = Condition.If;

class CalculatorModal extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      tabs: [
        {name: messages('financial-account.key129')/*运算符*/, key: 'sign'},
        {name: messages('financial-account.key130')/*函数*/, key: 'func'}
      ],
      status: 'sign',
      signalList: constants.signalList,
      funcList: constants.funcList,
      activeItem: {},
      treeList: [],
      treeLoading: false,
      formulaJson: [
        {type: 'light'}
      ],
      saveLoading: false,
      wrongIndex: -1,
      lineCellId: '',
      functionSegments: [],
      activeId: '',
      expandedKeys: [],
      highLightId: '',
      childExpandedKeys: [],
      highExpandNode: ''
    };
  }

  componentDidMount() {
    this.getTreeList();
  }

  componentWillReceiveProps(nextProps) {
    if(nextProps.visible) {
      if (window.addEventListener) {
        window.addEventListener('keydown', this.handleKeyDown);
      } else {
        window.attachEvent('onkeydown', this.handleKeyDown);
      }
      if(!nextProps.infoData.isDcDirection)
        this.setState({treeList: nextProps.treeList});
      this.setState({
        formulaJson: [{type: 'light'}],
        wrongIndex: -1
      });
      if(nextProps.value){
        this.getFormulaJson();
      }
    } else {
      this.setState({functionSegments: [],activeId: ''});
      if (window.addEventListener) {
        window.removeEventListener('keydown', this.handleKeyDown);
      } else {
        window.detachEvent('onkeydown', this.handleKeyDown);
      }
    }
  }

  getTreeList = () => {
    const { infoData, treeList } = this.props;
    if(infoData.isDcDirection){
      this.setState({treeLoading: true});
      credentialService.getDebitTree({setOfBooksId: infoData.setOfBooksId}).then(res => {
        let temp = [];
        temp.push({
          data: {
            detailSourceName: res.data.dcName,
            id: res.data.id,
            functionSegments: []
          }
        });
        res.data.defineDetailList.map(item => {
          temp[0].data.functionSegments.push({
            id: item.directionCode,
            segmentName: item.directionName
          });
        });
        this.setState({
          treeList: temp,
          treeLoading: false
        });
      }).catch(e => {
        this.setState({treeLoading: false});
        message.error(e.response.data.message);
      })
    } else {
      this.setState({treeList: treeList});
    }
  };

  refAddEvent = (expandedKey,e) => {
    this.setState({ highExpandNode: '' });
    this.addDBClickEvent(e.node.props.eventKey);
    this.handleFindKey(e.node.props.eventKey);
  };

  handleTreeDetail = (expandedKey,e) => {
    this.childEvent(e.node.props.eventKey);
    this.handleChildKey(e.node.props.eventKey);
  };

  childEvent = (key, arrayList = this.state.functionSegments) => {
    setTimeout(() => {
      arrayList.map(item => {
        if(item.id === key){
          item.childNodes.map(record => {
            if (window.addEventListener) {
              if(ReactDOM.findDOMNode(this.refs[record.id])){
                ReactDOM.findDOMNode(this.refs[record.id]).addEventListener('dblclick',() => this.handleSegment(record));
              }
            } else {
              if(ReactDOM.findDOMNode(this.refs[record.id])){
                ReactDOM.findDOMNode(this.refs[record.id]).attachEvent('ondblclick',() => this.handleSegment(record));
              }
            }
          })
        }
      });
    }, 100)
  };

  handleChildKey = (key, arrayList = this.state.functionSegments) => {
    const { childExpandedKeys } = this.state;
    arrayList.map(item => {
      if (item.id === key) {
        let index = childExpandedKeys.indexOf(item.id);
        index > -1 ? childExpandedKeys.splice(index, 1) : childExpandedKeys.push(key);
        this.setState({ childExpandedKeys })
      } else {
        item.childNodes && this.handleChildKey(key, item.childNodes);
      }
    });
  };

  handleFindKey = (key, arrayList = this.state.treeList) => {
    let { expandedKeys } = this.state;
    arrayList.map(item => {
      if(item.data.id === key){
        let index = expandedKeys.indexOf(item.data.id);
        index > -1 ? expandedKeys.splice(index, 1) : expandedKeys.push(key);
        this.setState({functionSegments: item.data.functionSegments, expandedKeys})
      } else {
        item.childNodes && this.handleFindKey(key, item.childNodes);
      }
    });
  };

  addDBClickEvent = (key, arrayList = this.state.treeList) => {
    const { activeId } = this.state;
    setTimeout(() => {
      arrayList.map(item => {
        let node = item.data;
        let childNode = item.childNodes;
        if(node){
          childNode && this.addDBClickEvent(key, childNode);
          activeId !== key && node.functionSegments && this.addDBClickEvent(key, node.functionSegments);
        } else {
          if (window.addEventListener) {
            if(ReactDOM.findDOMNode(this.refs[item.id])){
              ReactDOM.findDOMNode(this.refs[item.id]).addEventListener('dblclick',() => this.handleSegment(item));
              this.setState({activeId: key});
            }
          } else {
            if(ReactDOM.findDOMNode(this.refs[item.id])){
              ReactDOM.findDOMNode(this.refs[item.id]).attachEvent('ondblclick',() => this.handleSegment(item));
              this.setState({activeId: key});
            }
          }
        }
      })
    },100)
  };

  getFormulaJson = () => {
    const { infoData } = this.props;
    let temp = {
      templateId: infoData.templateId,
      lineDefineId: infoData.lineDefineId
    };
    infoData.journalTemplateSceneId && (temp.journalTemplateSceneId = infoData.journalTemplateSceneId);
    credentialService.getCalculator(temp).then(res => {
      let editArray = [];
      let chain = [];
      let tempArray = deepFullCopy(res.data);
      if(tempArray.length === 1 && tempArray[0].directValue){
        let item = tempArray[0];
        this.setState({lineCellId: item.id});
        let tempObj = {refId: this.getRandomRef()};
        if(item.calculateType === 8000){
          tempObj.type = 'constantTag';
          tempObj.name = item.directValue;
          tempObj.value = item.directValue;
        } else {
          tempObj.type = 'segmentTag';
          tempObj.name = item.segmentName;
          tempObj.value = item.directValue;
        }
        editArray.push(tempObj);
      } else {
        tempArray.map(item => {
          if(item.sequence === 1){
            chain = this.getChain(chain,tempArray,item,0).res;
            this.setState({lineCellId: item.id});
          }
        });
        chain.map(item => {
          if(item.directValue){
            let tempObj = {refId: this.getRandomRef()};
            if(item.calculateType === 8000){
              tempObj.type = 'constantTag';
              tempObj.name = item.directValue;
              tempObj.value = item.directValue;
            } else {
              tempObj.type = 'segmentTag';
              tempObj.name = item.segmentName;
              tempObj.value = item.directValue;
            }
            editArray.push(tempObj);
          } else if(item.journalCellDetail) {
            editArray = this.chainToTree(editArray,item.journalCellDetail);
          } else {
            editArray.push(item);
          }
        })
      }
      editArray.push({type: 'light'});
      editArray = this.handleClose(editArray).tempArray;
      this.setState({formulaJson: editArray})
    }).catch(e => {
      message.error(e.response.data.message);
    })
  };

  getChain = (res, array, obj, index) => {
    let startId = obj.journalCellDetail && obj.journalCellDetail.paramStartType === 1003 ? obj.journalCellDetail.paramStartValue : null;
    let endId = obj.journalCellDetail && obj.journalCellDetail.paramEndType === 1003 ? obj.journalCellDetail.paramEndValue : null;
    let calculateCellId = obj.journalCellDetail && obj.journalCellDetail.calculateCellId ? obj.journalCellDetail.calculateCellId.toString() : null;
    let cellLabels = obj.cellLabels === 1;
    if(cellLabels){
      res.splice(index,0,{type: '<brackets'});
      index += 1;
      let copyObj = deepFullCopy(obj);
      delete copyObj.cellLabels;
      let temp = this.getChain(res,array,copyObj,index);
      res = temp.res;
      index = temp.index;
      res.splice(index,0,{type: '/brackets'});
      index += 1;
    } else if(calculateCellId){
      obj.journalCellDetail.detailType === 2001 ? res.splice(index,0,{type: '<if'}) : res.splice(index,0,{type: '<mid'});
      index += 1;
      array.map(item => {
        if(item.id === calculateCellId){
          let temp = this.getChain(res,array,item,index);
          res = temp.res;
          index = temp.index;
          res.splice(index,0,{type: '/judge'});
          index += 1;
        }
      });
      array.map(item => {
        if(startId){
          if(item.id === startId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      });
      res.splice(index,0,{type: '/right'});
      index += 1;
      array.map(item => {
        if(endId){
          if(item.id === endId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      });
      res.splice(index,0,{type: '/wrong'});
      index += 1;
    } else if(obj.journalCellDetail && obj.journalCellDetail.detailType === 4001){
      res.splice(index,0,{type: '<date'});
      index += 1;
      array.map(item => {
        if(startId){
          if(item.id === startId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      });
      res.splice(index,0,{type: '/segmentDate'});
      index += 1;
      array.map(item => {
        if(endId){
          if(item.id === endId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      });
      res.splice(index,0,{type: '/date'});
      index += 1;
    } else if(obj.journalCellDetail && obj.journalCellDetail.detailType === 2005){
      res.splice(index,0,{type: '<len'});
      index += 1;
      array.map(item => {
        if(startId){
          if(item.id === startId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      });
      res.splice(index,0,{type: '/len'});
      index += 1;
    } else {
      res.splice(index,0,obj);
      if (!startId) {
        index += 1;
      }
      array.map(item => {
        if(startId){
          if(item.id === startId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index + 1;
          }
        }
      });
      array.map(item => {
        if(endId){
          if(item.id === endId){
            let temp = this.getChain(res,array,item,index);
            res = temp.res;
            index = temp.index;
          }
        }
      })
    }
    return {res,index};
  };

  chainToTree = (arr,obj) => {
    switch (obj.paramStartType) {
      case 1002:
        arr.push({
          type: 'segmentTag',
          name: obj.startSegmentName,
          value: obj.paramStartValue,
          refId: this.getRandomRef()
        });
        break;
      case 1001:
        arr.push({
          type: 'constantTag',
          name: obj.paramStartValue,
          value: obj.paramStartValue,
          refId: this.getRandomRef()
        });
        break;
      default:
        break;
    }
    obj.detailType === 5001 && (arr.push({ type: 'getAccountName', value: '5001' }));
    constants.signalList.map(item => {
      if(Number(item.id) === obj.detailType){
        arr.push({
          type: 'signTag',
          name: item.sign,
          value: item.id,
          priority: item.priority,
          refId: this.getRandomRef()
        });
      }
    });
    switch (obj.paramEndType) {
      case 1002:
        arr.push({
          type: 'segmentTag',
          name: obj.endSegmentName,
          value: obj.paramEndValue,
          refId: this.getRandomRef()
        });
        break;
      case 1001:
        arr.push({
          type: 'constantTag',
          name: obj.paramEndValue,
          value: obj.paramEndValue,
          refId: this.getRandomRef()
        });
        break;
      default:
        break;
    }
    return arr;
  };

  handleKeyDown = e => {
    let keyCode = e.keyCode || e.which || e.charCode;
    switch (keyCode) {
      case 8:
        // 退格
        this.handleDelete();
        break;
      case 37:
        // ⬅️
        this.handleToLeft();
        break;
      case 39:
        // ➡️
        this.handleToRight();
        break;
      default:
        break;
    }
  };

  handleDelete = () => {
    let { formulaJson } = this.state;
    let tempArray = this.handleOpen();
    let afterDeleteObj = this.arrayDelete(tempArray);
    tempArray = afterDeleteObj.mapArray;
    let afterCloseObj = this.handleClose(tempArray);
    formulaJson = afterCloseObj.tempArray;
    if(afterDeleteObj.isExtra){
      let temp = {};
      afterCloseObj.copyWrite.every((record,index) => {
        if(index === 0){
          if(index === afterCloseObj.copyWrite.length - 1){
            formulaJson[record.index] = {type: 'light'};
            return false;
          } else {
            temp = formulaJson[record.index].detail[record.type];
            return true;
          }
        } else {
          if(index === afterCloseObj.copyWrite.length - 1){
            temp[record.index] = {type: 'light'};
            return false;
          } else {
            temp = temp[record.index].detail[record.type];
            return true;
          }
        }
      });
    }
    this.setState({ formulaJson, wrongIndex: -1 });
  };

  arrayDelete = (mapArray) => {
    let isExtra = false;
    mapArray.map((item,index) => {
      if(item.type === 'light'){
        if(index !== 0){
          let temp = mapArray[index - 1];
          let inventedType = ['/judge','/right','/wrong','/brackets','/segmentDate','/date'];
          if(~inventedType.indexOf(temp.type)){
            mapArray[index] = mapArray[index - 1];
            mapArray[index - 1] = item;
            let recursionObj = this.arrayDelete(mapArray);
            mapArray = recursionObj.mapArray;
            isExtra = recursionObj.isExtra;
            return false;
          } else {
            let extraType = ['<if','<brackets','<mid','<date'];
            if(~extraType.indexOf(temp.type)){
              isExtra = true;
              return false;
            } else {
              mapArray.splice(index - 1, 1);
              return false;
            }
          }
        }
      } else {
        return true;
      }
    });
    return {mapArray,isExtra};
  };

  handleToLeft = () => {
    let tempArray = this.handleOpen();
    tempArray.map((item,index) => {
      if(item.type === 'light'){
        if(index !== 0){
          let temp = tempArray[index];
          tempArray[index] = tempArray[index - 1];
          tempArray[index - 1] = temp;
        }
      }
    });
    let temp = this.handleClose(tempArray).tempArray;
    this.setState({ formulaJson: temp });
  };

  handleToRight = () => {
    let tempArray = this.handleOpen();
    tempArray.every((item,index) => {
      if(item.type === 'light'){
        if(index !== tempArray.length - 1){
          let temp = tempArray[index];
          tempArray[index] = tempArray[index + 1];
          tempArray[index + 1] = temp;
          return false;
        }
      } else {
        return true;
      }
    });
    let temp = this.handleClose(tempArray).tempArray;
    this.setState({ formulaJson: temp });
  };

  handleOpen = (mapArray = this.state.formulaJson, tempArray = []) => {
    mapArray.map(item => {
      if(item.type !== 'if' && item.type !== 'brackets' && item.type !== 'mid' && item.type !== 'date' && item.type !== 'len'){
        tempArray.push(item);
      } else {
        if(item.type === 'brackets'){
          tempArray.push({type:'<brackets'});
          tempArray = this.handleOpen(item.detail.content,tempArray);
          tempArray.push({type:'/brackets'});
        } else if(item.type === 'mid' || item.type === 'if') {
          item.type === 'if' ? tempArray.push({type:'<if'}) : tempArray.push({type:'<mid'});
          tempArray = this.handleOpen(item.detail.judge,tempArray);
          tempArray.push({type:'/judge'});
          tempArray = this.handleOpen(item.detail.right,tempArray);
          tempArray.push({type:'/right'});
          tempArray = this.handleOpen(item.detail.wrong,tempArray);
          tempArray.push({type:'/wrong'});
        } else if (item.type === 'date') {
          tempArray.push({type:'<date'});
          tempArray = this.handleOpen(item.detail.segmentDate,tempArray);
          tempArray.push({type:'/segmentDate'});
          tempArray = this.handleOpen(item.detail.date,tempArray);
          tempArray.push({type:'/date'});
        } else if (item.type === 'len') {
          tempArray.push({type:'<len'});
          tempArray = this.handleOpen(item.detail.len,tempArray);
          tempArray.push({type:'/len'});
        }
      }
    });
    return tempArray;
  };

  handleClose = (mapArray, tempArray = []) => {
    let inventedType = ['<if','/judge','/right','/wrong','<brackets','/brackets','<mid','<date','/segmentDate','/date','<len','/len'];
    let write = [];
    let copyWrite = [];
    let temp = {};
    mapArray.map(item => {
      if(inventedType.indexOf(item.type) === -1){
        if(item.type === 'light'){
          copyWrite = JSON.parse(JSON.stringify(write));
        }
        if(write.length){
          write.map((record,index) => {
            if(index === 0){
              temp = tempArray[record.index].detail[record.type];
            } else {
              temp = temp[record.index].detail[record.type];
            }
            if(index === write.length - 1){
              temp.push(item);
            }
          });
        } else {
          tempArray.push(item);
        }
      } else {
        if(item.type === '<if'){
          if(!write.length){
            tempArray.push({type: 'if', name: 'IF', value: '2001', mapCellId: item.mapCellId, detail: { judge: [], right: [], wrong: [] }});
            write.push({index: tempArray.length - 1, type: 'judge'});
          } else {
            let tempIndex = 0;
            write.map((record,index) => {
              if(index === 0){
                temp = tempArray[record.index].detail[record.type];
              } else {
                temp = temp[record.index].detail[record.type];
              }
              if(index === write.length - 1){
                temp.push({type: 'if', name: 'IF', value: '2001', mapCellId: item.mapCellId, detail: { judge: [], right: [], wrong: [] }});
                tempIndex = temp.length - 1;
              }
            });
            write.push({index: tempIndex, type: 'judge'});
          }
        }
        if(item.type === '<mid'){
          if(!write.length){
            tempArray.push({type: 'mid', name: 'MID', value: '2004', mapCellId: item.mapCellId, detail: { judge: [], right: [], wrong: [] }});
            write.push({index: tempArray.length - 1, type: 'judge'});
          } else {
            let tempIndex = 0;
            write.map((record,index) => {
              if(index === 0){
                temp = tempArray[record.index].detail[record.type];
              } else {
                temp = temp[record.index].detail[record.type];
              }
              if(index === write.length - 1){
                temp.push({type: 'mid', name: 'MID', value: '2004', mapCellId: item.mapCellId, detail: { judge: [], right: [], wrong: [] }});
                tempIndex = temp.length - 1;
              }
            });
            write.push({index: tempIndex, type: 'judge'});
          }
        }
        if(item.type === '<date'){
          if(!write.length){
            tempArray.push({type: 'date', name: 'DATE', value: '4001', mapCellId: item.mapCellId, detail: { segmentDate: [], date: [] }});
            write.push({index: tempArray.length - 1, type: 'segmentDate'});
          } else {
            let tempIndex = 0;
            write.map((record,index) => {
              if(index === 0){
                temp = tempArray[record.index].detail[record.type];
              } else {
                temp = temp[record.index].detail[record.type];
              }
              if(index === write.length - 1){
                temp.push({type: 'date', name: 'DATE', value: '4001', mapCellId: item.mapCellId, detail: { segmentDate: [], date: [] }});
                tempIndex = temp.length - 1;
              }
            });
            write.push({index: tempIndex, type: 'segmentDate'});
          }
        }
        if(item.type === '/judge'){
          write[write.length - 1].type = 'right';
        }
        if(item.type === '/segmentDate'){
          write[write.length - 1].type = 'date';
        }
        if(item.type === '/right'){
          write[write.length - 1].type = 'wrong';
        }
        if(item.type === '/wrong' || item.type === '/brackets' || item.type === '/date' || item.type === '/len'){
          write.splice(write.length - 1,1);
        }
        if(item.type === '<brackets'){
          if(!write.length){
            tempArray.push({type: 'brackets', detail: { content: [] }});
            write.push({index: tempArray.length - 1, type: 'content'});
          } else {
            let tempIndex = 0;
            write.map((record,index) => {
              if(index === 0){
                temp = tempArray[record.index].detail[record.type];
              } else {
                temp = temp[record.index].detail[record.type];
              }
              if(index === write.length - 1){
                temp.push({type: 'brackets', detail: { content: [] }});
                tempIndex = temp.length - 1;
              }
            });
            write.push({index: tempIndex, type: 'content'});
          }
        }
        if (item.type === '<len') {
          if(!write.length){
            tempArray.push({type: 'len', name: 'Len', value: '2005', mapCellId: item.mapCellId, detail: { len: [] }});
            write.push({index: tempArray.length - 1, type: 'len'});
          } else {
            let tempIndex = 0;
            write.map((record,index) => {
              if(index === 0){
                temp = tempArray[record.index].detail[record.type];
              } else {
                temp = temp[record.index].detail[record.type];
              }
              if(index === write.length - 1){
                temp.push({type: 'len', name: 'Len', value: '2005', mapCellId: item.mapCellId, detail: { len: [] }});
                tempIndex = temp.length - 1;
              }
            });
            write.push({index: tempIndex, type: 'len'});
          }
        }
      }
    });
    return {tempArray,copyWrite};
  };

  handleOk = () => {
    const { formulaJson, lineCellId } = this.state;
    const { onOk } = this.props;
    let copyData = deepFullCopy(formulaJson);
    if(formulaJson.length === 1 && formulaJson[0].type === 'light'){
      if(lineCellId){
        this.setState({saveLoading: true});
        credentialService.deleteCalculator({lineCellId}).then(() => {
          this.setState({saveLoading: false},() => {
            onOk('');
          });
        }).catch(e => {
          message.error(e.response.data.message);
          this.setState({saveLoading: false, formulaJson: copyData});
        })
      } else {
        onOk('');
      }
    } else {
      let checkResult = this.checkValid();
      if(checkResult.isValid){
        let tempArray = this.handleOpen();
        tempArray.every((item,index) => {
          if(item.type === 'light'){
            tempArray.splice(index,1);
            return false;
          }
          return true;
        });
        let cellComment = '';
        tempArray.map((item,index) => {
          switch (item.type){
            case '/judge':
            case '/right':
            case '/segmentDate':
              cellComment += ',';
              break;
            case '<if':
              item.mapCellId = index.toString();
              cellComment += 'IF(';
              break;
            case '<mid':
              item.mapCellId = index.toString();
              cellComment += 'MID(';
              break;
            case '<date':
              item.mapCellId = index.toString();
              cellComment += 'DATE(';
              break;
            case '<brackets':
              cellComment += '(';
              break;
            case '<len':
              item.mapCellId = index.toString();
              cellComment += 'Len(';
              break;
            case '/wrong':
            case '/brackets':
            case '/date':
            case '/len':
              cellComment += ')';
              break;
            case 'light':
              tempArray[index] = undefined;
              break;
            case 'getAccountName':
              item.mapCellId = index.toString();
              cellComment += 'GetAccountName()';
              break;
            default:
              item.mapCellId = index.toString();
              cellComment += item.name;
              break;
          }
        });
        tempArray = tempArray.filter(item => !!item);
        let noneLight = this.handleClose(tempArray).tempArray;
        this.setState({formulaJson: noneLight},() => {
          this.handleSave(cellComment, copyData)
        });
      } else {
        this.setState({ wrongIndex: checkResult.wrongIndex});
      }
    }
  };

  checkValid = (arr = this.state.formulaJson, isJudge = false) => {
    let res = [];
    let isValid = true;
    let wrongIndex = -1;
    arr.every((item, index) => {
      switch (item.type){
        case 'segmentTag':
        case 'getAccountName':
          res.push('(1)');
          break;
        case 'constantTag':
          if(item.name.length === 0){
            wrongIndex = index;
            isValid = false;
            message.error(messages('financial-account.key152')/*常量不为空*/);
            return false;
          } else {
            res.push('(1)');
          }
          break;
        case 'if':
          isValid = this.checkValid(item.detail.judge, true).isValid;
          if(isValid){
            if(item.detail.right.length !== 0){
              isValid = this.checkValid(item.detail.right).isValid;
            }
            if(isValid){
              if(item.detail.wrong.length !== 0){
                isValid = this.checkValid(item.detail.wrong).isValid;
              }
              if(isValid){
                res.push('(1)');
              } else {
                wrongIndex = index;
                return false;
              };
            } else {
              wrongIndex = index;
              return false;
            }
          } else {
            wrongIndex = index;
            return false;
          }
          break;
        case 'mid':
          let copyItem = JSON.parse(JSON.stringify(item));
          copyItem = this.handleOpen([copyItem]);
          copyItem.filter((it,i) => it.type === 'light' && copyItem.splice(i,1));
          copyItem = this.handleClose(copyItem).tempArray[0];
          if(this.checkValid(item.detail.judge).isValid &&
            copyItem.detail.right.length === 1 && this.isNumber(copyItem.detail.right[0].value) && copyItem.detail.right[0].type === 'constantTag' &&
            copyItem.detail.wrong.length === 1 && this.isNumber(copyItem.detail.wrong[0].value) && copyItem.detail.wrong[0].type === 'constantTag'){
            res.push('(1)');
          } else {
            wrongIndex = index;
            return false;
          }
          break;
        case 'date':
          let copyObj = JSON.parse(JSON.stringify(item));
          copyObj = this.handleOpen([copyObj]);
          copyObj.filter((it,i) => it.type === 'light' && copyObj.splice(i,1));
          copyObj = this.handleClose(copyObj).tempArray[0];
          if(copyObj.detail.segmentDate.length === 1 && this.checkValid(item.detail.segmentDate).isValid &&
            copyObj.detail.date.length === 1 && copyObj.detail.date[0].type === 'constantTag'){
            res.push('(1)');
          } else {
            wrongIndex = index;
            return false;
          }
          break;
        case 'signTag':
          if(!isJudge) {
            if(Number(item.value) > 3000){
              isValid = false;
              message.error(messages('financial-account.key154')/*逻辑运算出现位置不合法*/);
              wrongIndex = index;
              return false;
            }
          }
          res.push('+');
          break;
        case 'brackets':
        case 'len':
          isValid = this.checkValid(item.detail.content || item.detail.len).isValid;
          if(isValid){
            res.push('(1)');
          } else {
            wrongIndex = index;
            return false;
          };
          break;
        default:
          break;
      };
      return true;
    });
    if(isValid){
      try {
        if(res[0] !== '(1)'){
          message.error(messages('financial-account.key155')/*公式不合法*/);
          isValid = false;
        } else {
          eval(res.join(''));
        }
      } catch (e) {
        message.error(messages('financial-account.key155')/*公式不合法*/);
        isValid = false;
      }
    }
    return {isValid,wrongIndex};
  };

  isNumber = str => {
    return /^\d+$/g.test(str);
  };

  handleSave = (cellComment, copyData) => {
    const { onOk } = this.props;
    let { formulaJson } = this.state;
    let temp = this.treeToChain([],formulaJson,cellComment).temp;
    this.setState({saveLoading: true});
    credentialService.saveCalculator(temp).then(res => {
      this.setState({saveLoading: false},() => {
        onOk(res.data.cellComment);
      });
    }).catch(e => {
      message.error(e.response.data.message);
      this.setState({saveLoading: false, formulaJson: copyData});
    })
  };

  treeToChain = (temp,arr,cellComment,isBra = false) => {
    const { infoData } = this.props;
    let segmentStack = [];
    let signStack = [];
    let calIndex = -1;
    let randomId = '';
    let reArray = ['if', 'brackets', 'mid', 'date', 'getAccountName', 'len'];
    let funcArray = ['cell', 'if', 'brackets', 'mid', 'date', 'getAccountName', 'len'];
    arr.map((item,index) => {
      if(index !== calIndex){
        if(item.type === 'signTag'){
          if(signStack.length > 0){
            let signObj = signStack[0];
            if(signObj.priority < item.priority){
              calIndex = index + 1;
              let segmentObj = segmentStack.pop();
              let calObj = {
                mapCellId: item.mapCellId,
                lineDefineId: infoData.lineDefineId,
                templateId: infoData.templateId,
                journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
                calculateType: Math.floor(item.value / 1000) * 1000,
                journalCellDetail: {
                  paramStartType: (funcArray.indexOf(segmentObj.type) > -1) ? 1003 : (segmentObj.type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
                  paramStartValue: segmentObj.value,
                  startSegmentName: segmentObj.type === 'segmentTag' ? segmentObj.name : null,
                  calculateType: Math.floor(item.value / 1000) * 1000,
                  detailType: item.value,
                  paramEndType: (funcArray.indexOf(arr[index + 1].type) > -1) ? 1003 : (arr[index + 1].type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
                  paramEndValue: arr[index + 1].value,
                  endSegmentName: arr[index + 1].type === 'segmentTag' ? arr[index + 1].name : null,
                }
              };
              if ((infoData.isDcDirection && segmentObj.type ==='segmentTag') || (reArray.indexOf(segmentObj.type) > -1)) {
                let ifObj = this.treeToChain(temp,[segmentObj]);
                temp = ifObj.temp;
                calObj.mapDetailStartId = ifObj.randomId;
              }
              if ((infoData.isDcDirection && arr[index + 1].type ==='segmentTag') || (reArray.indexOf(arr[index + 1].type) > -1)) {
                let ifObj = this.treeToChain(temp,[arr[index + 1]]);
                temp = ifObj.temp;
                calObj.mapDetailEndId = ifObj.randomId;
              }
              segmentObj.type === 'cell' && (calObj.mapDetailStartId = segmentObj.value);
              segmentStack.push({type: 'cell', value: calObj.mapCellId});
              temp.push(calObj);
            } else {
              signStack.pop();
              signStack.push(item);
              let calObj = {
                mapCellId: signObj.mapCellId,
                lineDefineId: infoData.lineDefineId,
                templateId: infoData.templateId,
                journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
                calculateType: Math.floor(signObj.value / 1000) * 1000,
                journalCellDetail: {
                  paramStartType: (funcArray.indexOf(segmentStack[0].type) > -1) ? 1003 : (segmentStack[0].type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
                  paramStartValue: segmentStack[0].value,
                  startSegmentName: segmentStack[0].type === 'segmentTag' ? segmentStack[0].name : null,
                  calculateType: Math.floor(signObj.value / 1000) * 1000,
                  detailType: signObj.value,
                  paramEndType: (funcArray.indexOf(segmentStack[1].type) > -1) ? 1003 : (segmentStack[1].type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
                  paramEndValue: segmentStack[1].value,
                  endSegmentName: segmentStack[1].type === 'segmentTag' ? segmentStack[1].name : null,
                }
              };
              segmentStack[0].type === 'cell' && (calObj.mapDetailStartId = segmentStack[0].value);
              segmentStack[1].type === 'cell' && (calObj.mapDetailEndId = segmentStack[1].value);
              if((infoData.isDcDirection && segmentStack[0].type ==='segmentTag') || (reArray.indexOf(segmentStack[0].type) > -1)){
                let ifObj = this.treeToChain(temp,[segmentStack[0]]);
                temp = ifObj.temp;
                calObj.mapDetailStartId = ifObj.randomId;
              }
              if ((infoData.isDcDirection && segmentStack[1].type ==='segmentTag') || (reArray.indexOf(segmentStack[1].type) > -1)) {
                let ifObj = this.treeToChain(temp,[segmentStack[1]]);
                temp = ifObj.temp;
                calObj.mapDetailEndId = ifObj.randomId;
              }
              segmentStack = [];
              segmentStack.push({type: 'cell', value: calObj.mapCellId});
              temp.push(calObj);
            }
          } else {
            signStack.push(item);
          }
        } else {
          segmentStack.push(item);
        }
      }
    });
    if(segmentStack.length > 1){
      let calObj = {
        mapCellId: signStack[0].mapCellId,
        lineDefineId: infoData.lineDefineId,
        templateId: infoData.templateId,
        journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
        calculateType: Math.floor(signStack[0].value / 1000) * 1000,
        journalCellDetail: {
          paramStartType: (funcArray.indexOf(segmentStack[0].type) > -1) ? 1003 : (segmentStack[0].type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
          paramStartValue: segmentStack[0].value,
          startSegmentName: segmentStack[0].type === 'segmentTag' ? segmentStack[0].name : null,
          calculateType: Math.floor(signStack[0].value / 1000) * 1000,
          detailType: signStack[0].value,
          paramEndType: (funcArray.indexOf(segmentStack[1].type) > -1) ? 1003 : (segmentStack[1].type === 'constantTag' ? 1001 : (infoData.isDcDirection ? 1003 : 1002)),
          paramEndValue: segmentStack[1].value,
          endSegmentName: segmentStack[1].type === 'segmentTag' ? segmentStack[1].name : null,
        }
      };
      if(cellComment){
        calObj.cellComment = cellComment;
        calObj.sequence = 1;
      }
      if(isBra){
        calObj.cellLabels = 1;
      }
      if ((infoData.isDcDirection && segmentStack[0].type ==='segmentTag') || (reArray.indexOf(segmentStack[0].type) > -1)) {
        let ifObj = this.treeToChain(temp,[segmentStack[0]]);
        temp = ifObj.temp;
        calObj.mapDetailStartId = ifObj.randomId;
      }
      if ((infoData.isDcDirection && segmentStack[1].type ==='segmentTag') || (reArray.indexOf(segmentStack[1].type) > -1)) {
        let ifObj = this.treeToChain(temp,[segmentStack[1]]);
        temp = ifObj.temp;
        calObj.mapDetailEndId = ifObj.randomId;
      }
      segmentStack[0].type === 'cell' && (calObj.mapDetailStartId = segmentStack[0].value);
      segmentStack[1].type === 'cell' && (calObj.mapDetailEndId = segmentStack[1].value);
      temp.push(calObj);
      randomId = signStack[0].mapCellId;
    } else {
      if(segmentStack[0].type === 'if' || segmentStack[0].type === 'mid'){
        let calObj = {
          mapCellId: segmentStack[0].mapCellId,
          lineDefineId: infoData.lineDefineId,
          templateId: infoData.templateId,
          journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
          calculateType: 2000,
          journalCellDetail:{
            paramStartType: 1003,
            calculateType: 2000,
            detailType: segmentStack[0].type === 'if' ? 2001 : 2004,
            paramEndType: 1003,
          }
        };
        let judgeObj = this.treeToChain(temp,segmentStack[0].detail.judge);
        temp = judgeObj.temp;
        calObj.mapDetailCalculateId = judgeObj.randomId;
        if(segmentStack[0].detail.right.length !== 0){
          let rightObj = this.treeToChain(temp,segmentStack[0].detail.right);
          temp = rightObj.temp;
          calObj.mapDetailStartId = rightObj.randomId;
        } else {
          calObj.mapDetailStartId = null;
        }
        if(segmentStack[0].detail.wrong.length !== 0){
          let wrongObj = this.treeToChain(temp,segmentStack[0].detail.wrong);
          temp = wrongObj.temp;
          calObj.mapDetailEndId = wrongObj.randomId;
        } else {
          calObj.mapDetailEndId = null;
        }
        if(cellComment){
          calObj.cellComment = cellComment;
          calObj.sequence = 1;
        }
        if(isBra){
          calObj.cellLabels = 1;
        }
        temp.push(calObj);
        randomId = segmentStack[0].mapCellId;
      } else if (segmentStack[0].type === 'date') {
        let calObj = {
          mapCellId: segmentStack[0].mapCellId,
          lineDefineId: infoData.lineDefineId,
          templateId: infoData.templateId,
          journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
          calculateType: 4000,
          journalCellDetail: {
            paramStartType: 1003,
            calculateType: 4000,
            detailType: 4001,
            paramEndType: 1003,
          }
        };
        let rightObj = this.treeToChain(temp,segmentStack[0].detail.segmentDate);
        temp = rightObj.temp;
        calObj.mapDetailStartId = rightObj.randomId;
        let wrongObj = this.treeToChain(temp,segmentStack[0].detail.date);
        temp = wrongObj.temp;
        calObj.mapDetailEndId = wrongObj.randomId;
        if(cellComment){
          calObj.cellComment = cellComment;
          calObj.sequence = 1;
        }
        if(isBra){
          calObj.cellLabels = 1;
        }
        temp.push(calObj);
        randomId = segmentStack[0].mapCellId;
      } else if(segmentStack[0].type === 'len') {
        let calObj = {
          mapCellId: segmentStack[0].mapCellId,
          lineDefineId: infoData.lineDefineId,
          templateId: infoData.templateId,
          journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
          calculateType: 2000,
          journalCellDetail: {
            paramStartType: 1003,
            calculateType: 2000,
            detailType: 2005,
          }
        };
        let judgeObj = this.treeToChain(temp,segmentStack[0].detail.len);
        temp = judgeObj.temp;
        calObj.mapDetailStartId = judgeObj.randomId;
        if(cellComment){
          calObj.cellComment = cellComment;
          calObj.sequence = 1;
        }
        if(isBra){
          calObj.cellLabels = 1;
        }
        temp.push(calObj);
        randomId = segmentStack[0].mapCellId;
      } else if(segmentStack[0].type === 'brackets') {
        let judgeObj = this.treeToChain(temp,segmentStack[0].detail.content,undefined,true);
        temp = judgeObj.temp;
        randomId = judgeObj.randomId;
        temp.map(pair => {
          if(pair.mapCellId === randomId){
            if(cellComment){
              pair.sequence = 1;
              pair.cellComment = cellComment;
            }
            if(isBra){
              pair.cellLabels = 1;
            }
          }
        })
      } else if (segmentStack[0].type === 'getAccountName') {
        let calObj = {
          mapCellId: segmentStack[0].mapCellId,
          lineDefineId: infoData.lineDefineId,
          templateId: infoData.templateId,
          journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
          calculateType: 5000,
          journalCellDetail: {
            calculateType: 5000,
            detailType: 5001
          }
        };
        if(cellComment){
          calObj.cellComment = cellComment;
          calObj.sequence = 1;
        }
        if(isBra){
          calObj.cellLabels = 1;
        }
        temp.push(calObj);
        randomId = segmentStack[0].mapCellId;
      } else {
        let calObj = {
          mapCellId: segmentStack[0].mapCellId,
          lineDefineId: infoData.lineDefineId,
          templateId: infoData.templateId,
          journalTemplateSceneId: infoData.journalTemplateSceneId ? infoData.journalTemplateSceneId : null,
          calculateType: segmentStack[0].type === 'constantTag' ? 8000 : (infoData.isDcDirection ? 8001 : 9000),
          directValue: segmentStack[0].type === 'constantTag' ? segmentStack[0].name : segmentStack[0].value,
          segmentName: segmentStack[0].type === 'segmentTag' ? segmentStack[0].name : null
        };
        if(cellComment){
          calObj.cellComment = cellComment;
          calObj.sequence = 1;
        }
        if(isBra){
          calObj.cellLabels = 1;
        }
        temp.push(calObj);
        randomId = segmentStack[0].mapCellId;
      }
    }
    return {temp,randomId};
  };

  onChangeTabs = key => {
    this.setState({status: key, activeItem: {}});
  };

  handleClick = item => {
    this.setState({activeItem: item});
  };

  loop = data => data.map((item) => {
    const { highExpandNode } = this.state;
    if(item.data){
      let node = item.data;
      let childNode = item.childNodes || [];
      return <TreeNode key={node.id} title={<div onClick={() => {
        this.setState({ highExpandNode: '' });
        this.addDBClickEvent(node.id);
        this.handleFindKey(node.id);
      }} style={ highExpandNode === node.id ? { color: '#fff', backgroundColor: '#FF6680' } : {} }>{node.detailSourceName}</div>} ref={node.id}>
        { childNode && this.loop(childNode) }
      </TreeNode>
    }
  });

  renderFunction = data => data.map(item => {
    const { highLightId } = this.state;
    if(item.childNodes && item.childNodes.length){
      return <TreeNode key={item.id} title={<div key={item.id} ref={item.id} className={highLightId === item.id && 'high-light'}>{item.segmentName}</div>}>
        { item.childNodes && this.renderFunction(item.childNodes) }
      </TreeNode>
    }
    return (
      <TreeNode
        key={item.id}
        title={ <div key={item.id} ref={item.id} className={highLightId === item.id && 'high-light'} onClick={() => {
          this.childEvent(item.id);
          this.handleChildKey(item.id);
        }}>{item.segmentName}</div> }
      />
    )
  });

  handleSegment = record => {
    let temp = this.handleClose(this.handleAddElement({type: 'segmentTag', name: record.segmentName, value: record.id, refId: this.getRandomRef()})).tempArray;
    this.setState({ formulaJson: temp });
  };

  handleSign = record => {
    let temp = {};
    if(record.id !== '10000'){
      temp = this.handleClose(this.handleAddElement({type: 'signTag', name: record.sign, value: record.id, priority: record.priority, refId: this.getRandomRef()})).tempArray;
    }else {
      temp = this.handleClose(this.handleAddElement({type: 'brackets'})).tempArray;
    }
    this.setState({ formulaJson: temp });
  };

  handleConstant = () => {
    let tempObj = {type: 'input', name: '', value: ''};
    let refId = this.getRandomRef();
    tempObj.refId = refId;
    let temp = this.handleClose(this.handleAddElement(tempObj)).tempArray;
    this.setState({ formulaJson: temp },() => {
      this.refs[refId].focus(refId);
    });
  };

  getRandomRef = () => {
    let id = Math.ceil(Math.random() * 100000).toString();
    if(this.refs.id){
      id = this.getRandomRef();
    }
    return id;
  };

  handleFunc = record => {
    let temp = this.handleClose(this.handleAddElement({
      type: record.type
    })).tempArray;
    this.setState({ formulaJson: temp });
  };

  handleAddElement = (elementObj) => {
    let tempArray = this.handleOpen();
    let eleMap = new Map([
      ['if',[{type: '<if'},{type: 'light'},{type: '/judge'},{type: '/right'},{type: '/wrong'}]],
      ['brackets',[{type: '<brackets'},{type: 'light'},{type: '/brackets'}]],
      ['mid',[
        {type: '<mid'},
        {type: 'light'},
        {type: '/judge'},
        {type: 'constantTag', name: '', value: '', refId: this.getRandomRef()},
        {type: '/right'},
        {type: 'constantTag', name: '', value: '', refId: this.getRandomRef()},
        {type: '/wrong'}]],
      ['date',[
        {type: '<date'},
        {type: 'constantTag', name: '当前日期', value: '当前日期', refId: this.getRandomRef()},
        {type: 'light'},
        {type: '/segmentDate'},
        {type: 'constantTag', name: 'YYYY-MM-DD', value: 'YYYY-MM-DD', refId: this.getRandomRef()},
        {type: '/date'}
      ]],
      ['len',[
        {type: '<len'},
        {type: 'light'},
        {type: '/len'},
      ]],
      ['getAccountName', [
        {type: 'getAccountName', value: '5001'},
        {type: 'light'}
      ]]
    ]);
    tempArray.every((item,index) => {
      if(item.type === 'light'){
        tempArray.splice(index,1);
        let responseArray = eleMap.get(elementObj.type) || [elementObj,{type: 'light'}];
        responseArray.map((item,i) => {
          tempArray.splice(index + i,0,item);
        });
        return false;
      }
      return true;
    });
    this.setState({wrongIndex: -1});
    return tempArray;
  };

  renderElement = ( objJson, style = {}, refresh = false ) => {
    const { wrongIndex } = this.state;
    return (
      <div style={style}>
        {objJson.map((item,index) => {
          let res = null;
          let wrongObj = {};
          refresh && index === wrongIndex && (wrongObj = {border: '1px solid red'});
          switch(item.type){
            case 'light':
              res = <span className='animation'/>;
              break;
            case 'signTag':
              res = <Tag closable onClose={(e) => this.handleCloseTag(e,item)} color="cyan" style={wrongObj} ref={item.refId}>{item.name}</Tag>;
              break;
            case 'input':
              res = <Input
                onBlur={e => this.handleInputConfirm(e,item)}
                style={wrongObj}
                onFocus={() => this.handleInputFocus(item.refId)}
                onChange={e => this.handleEnter(e,item)}
                value={item.name}
                ref={item.refId}
                onPaste={e => {
                  e.stopPropagation();
                  return false
                }}/>;
              break;
            case 'constantTag':
              res = <Tag closable onClose={(e) => this.handleCloseTag(e,item)} onClick={() => this.handleInputEnter(item)} style={wrongObj} ref={item.refId}>{item.name}</Tag>;
              break;
            case 'segmentTag':
              res = <Tag
                closable
                onClose={(e) => this.handleCloseTag(e,item)}
                onClick={() => {
                  this.setState({ expandedKeys: [], childExpandedKeys: [], highLightId: item.value }, () => {
                    this.getHighLight(item.value)
                  })
                }}
                color='#4B8DFF'
                style={wrongObj}
                ref={item.refId}>{item.name}</Tag>;
              break;
            case 'if':
              res = this.handleIf(item, wrongObj);
              break;
            case 'mid':
              res = this.handleMid(item, wrongObj);
              break;
            case 'brackets':
              res = this.handleBrackets(item, wrongObj);
              break;
            case 'date':
              res = this.handleDate(item,wrongObj);
              break;
            case 'len':
              res = this.handleLen(item,wrongObj);
              break;
            case 'getAccountName':
              res = this.handleGetAccountName(item,wrongObj);
              break;
            default:
              res = <div/>;
              break;
          };
          return res;
        })}
      </div>
    )
  };

  renderFormula = () => {
    const { formulaJson } = this.state;
    return (<div className='formula' onDoubleClick={() => this.handleConstant()} onPaste={this.handleParse}>
      {this.renderElement(formulaJson, {}, true)}
    </div>)
  };

  handleParse = e => {
    if ( e.clipboardData ) {
      try {
        e.clipboardData.items[0].getAsString(str => {
          const { treeList } = this.state;
          let reg = new RegExp('\\[([.\n\\s\\S]+?)\\]','g');
          str.replace(reg,(target, $1) => {
            let json = JSON.parse(`[${$1}]`);
            let isHave = true;
            this.handleOpen(json).map(item => {
              item.type === 'segmentTag' && JSON.stringify(treeList).indexOf(item.value) === -1 && (isHave = false);
            });
            if (isHave) {
              this.setState({ formulaJson: json })
            } else {
              message.error(messages('financial-account.key190')/*存在明细中不包含的字段*/);
            }
          });
        })
      } catch (e) {
        message.error(e)
      }
    }
    return false;
  };

  handleIf = (item, wrong = {}) => {
    const style = { verticalAlign: 'top',display: 'inline-block'};
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      IF({this.renderElement(item.detail.judge, style)},{this.renderElement(item.detail.right, style)},{this.renderElement(item.detail.wrong, style)})
    </div>)
  };

  handleMid = (item, wrong = {}) => {
    const style = { verticalAlign: 'top',display: 'inline-block'};
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      MID({this.renderElement(item.detail.judge, style)},{this.renderElement(item.detail.right, style)},{this.renderElement(item.detail.wrong, style)})
    </div>)
  };

  handleDate = (item, wrong = {}) => {
    const style = { verticalAlign: 'top',display: 'inline-block'};
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      DATE({this.renderElement(item.detail.segmentDate, style)},{this.renderElement(item.detail.date, style)})
    </div>)
  };

  handleLen = (item, wrong = {}) => {
    const style = { verticalAlign: 'top',display: 'inline-block'};
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      Len({this.renderElement(item.detail.len, style)})
    </div>)
  };

  handleGetAccountName = (item, wrong = {}) => {
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      GetAccountName()
    </div>)
  };

  handleBrackets = (item, wrong = {}) => {
    const style = { verticalAlign: 'top',display: 'inline-block'};
    let styleObj = Object.assign({verticalAlign: 'top',display: 'inline-block'},wrong);
    return (<div style={styleObj}>
      ({this.renderElement(item.detail.content, style)})
    </div>)
  };

  handleEnter = (e,record) => {
    let tempArray = this.handleOpen();
    tempArray.every(item => {
      if(item.refId === record.refId){
        item.name = e.target.value;
        return false;
      }
      return true;
    });
    this.setState({formulaJson: this.handleClose(tempArray).tempArray});
  };

  handleInputFocus = (refId) => {
    if (window.addEventListener) {
      window.removeEventListener('keydown', this.handleKeyDown);
    } else {
      window.detachEvent('onkeydown', this.handleKeyDown);
    }
    let tempArray = this.handleOpen();
    let isRefresh = false;
    tempArray.every((item,index) => {
      if(item.type === 'light'){
        tempArray.splice(index,1);
        isRefresh = true;
        return false;
      }
      return true;
    });
    this.setState({formulaJson: this.handleClose(tempArray).tempArray},() => {
      let length = this.refs[refId] ? this.refs[refId].props.value.length : 0;
      ReactDOM.findDOMNode(this.refs[refId]).setSelectionRange(length,length);
      isRefresh && this.refs[refId].focus(refId);
    });
  };

  handleInputConfirm = (e,record) => {
    if (window.addEventListener) {
      window.addEventListener('keydown', this.handleKeyDown);
    } else {
      window.attachEvent('onkeydown', this.handleKeyDown);
    }
    let tempArray = this.handleOpen();
    tempArray.every((item,index) => {
      if(item.refId === record.refId){
        tempArray[index] = {
          type: 'constantTag',
          name: e.target.value,
          value: e.target.value,
          refId: record.refId
        };
        tempArray.splice(index + 1,0,{type: 'light'});
        return false;
      }
      return true;
    });
    this.setState({formulaJson: this.handleClose(tempArray).tempArray, wrongIndex: -1});
  };

  handleInputEnter = (item) => {
    let tempArray = this.handleOpen();
    tempArray.every((record,index) => {
      if(record.refId === item.refId){
        tempArray[index] = {
          type: 'input',
          name: item.name,
          value: item.name,
          refId: item.refId
        };
        return false;
      }
      return true;
    });
    this.setState({formulaJson: this.handleClose(tempArray).tempArray},() => {
      this.refs[item.refId].focus(item.refId);
    });
  };

  handleCloseTag = (e, record) => {
    e.stopPropagation();
    e.preventDefault();
    let tempArray = this.handleOpen();
    tempArray.every((item,index) => {
      if(record.refId === item.refId){
        tempArray.splice(index,1);
        return false;
      }
      return true;
    });
    this.setState({formulaJson: this.handleClose(tempArray).tempArray, wrongIndex: -1});
  };

  getHighLight = (id, arr = this.state.treeList) => {
    let { expandedKeys } = this.state;
    arr.map(item => {
      if(JSON.stringify(item).indexOf(id) > -1){
        expandedKeys.push(item.data.id);
        this.setState({ expandedKeys }, () => {
          if (JSON.stringify(item.data.functionSegments).indexOf(id) === -1) {
            item.childNodes && this.getHighLight(id, item.childNodes);
          } else {
            this.setState({ functionSegments: item.data.functionSegments, highExpandNode: item.data.id }, () => {
              this.addDBClickEvent(item.data.id);
              this.handleChildExpanded(id);
            })
          }
        })
      }
    });
  };

  handleChildExpanded = (id, arr = this.state.functionSegments) => {
    let { childExpandedKeys } = this.state;
    arr.map(item => {
      if (JSON.stringify(item).indexOf(id) > -1) {
        if (item.id !== id) {
          childExpandedKeys.push(item.id);
          this.setState({ childExpandedKeys },() => {
            this.handleChildExpanded(id, item.childNodes);
          });
        } else {
          const { childExpandedKeys } = this.state;
          this.childEvent(childExpandedKeys[childExpandedKeys.length - 1]);
        }
      }
    })
  };

  onClickCopy = () => {
    message.success(messages('financial-account.key191')/*复制成功*/);
  };

  render(){
    const { visible, onCancel } = this.props;
    const { tabs, status, signalList, activeItem, funcList, treeLoading, saveLoading, treeList, functionSegments,
      expandedKeys, childExpandedKeys, formulaJson } = this.state;
    return(
      <div>
        <Modal visible={visible}
               footer={
                 <div>
                   <CopyToClipboard text={JSON.stringify(formulaJson)}>
                     <Button type='primary' onClick={this.onClickCopy}>{messages('common.copy')/*复制*/}</Button>
                   </CopyToClipboard>
                   <Button onClick={this.handleOk} type='primary' loading={saveLoading}>{messages('common.save')/*保存*/}</Button>
                   <Button onClick={onCancel}>{messages('common.cancel')/*取消*/}</Button>
                 </div>
               }
               onCancel={onCancel}
               className='calculator-modal'
               width={900}
               title={messages('financial-account.key131')/*公式编辑器*/}>
          <div>
            <Row className='big-row'>
              <Col span={4} className='big-col'>
                <div className='title'>{messages('financial-account.key132')/*取数*/}</div>
                <Spin spinning={treeLoading}>
                  <Tree onExpand={this.refAddEvent} expandedKeys={expandedKeys}>
                    {this.loop(treeList)}
                  </Tree>
                </Spin>
              </Col>
              <Col span={4} className="little-tree">
                <div className='title'>{messages('financial-account.key159')/*明细*/}</div>
                <div className={'little-tree-segment'}>
                  <Tree onExpand={this.handleTreeDetail} expandedKeys={childExpandedKeys}>
                    {this.renderFunction(functionSegments)}
                  </Tree>
                </div>
              </Col>
              <Col span={4} className='signal'>
                <Tabs onChange={this.onChangeTabs} defaultActiveKey={status}>
                  {tabs.map(item => {
                    return <TabPane key={item.key} tab={item.name}/>
                  })}
                </Tabs>
                <If value={status === 'sign'}>
                  <div className='signal-all'>
                    {
                      signalList.map(item => {
                        return <div onClick={() => this.handleClick(item)} onDoubleClick={() => this.handleSign(item)} className={`signal-single ${item.id === activeItem.id ? 'active' : ''}`}>{item.sign}</div>
                      })
                    }
                  </div>
                </If>
                <If value={status === 'func'}>
                  <div className='signal-all'>
                    {
                      funcList.map(item => {
                        return <div onClick={() => this.handleClick(item)} onDoubleClick={() => this.handleFunc(item)} className={`signal-single ${item.id === activeItem.id ? 'active' : ''}`}>{item.sign}</div>
                      })
                    }
                  </div>
                </If>
                <div className='description'>
                  <div style={{color:'rgba(0, 0, 0, 0.65)'}}>{messages('financial-account.key133')/*解释说明：*/}</div>
                  {activeItem.description}
                </div>
              </Col>
              <Col span={12} className='big-col'>
                <div className='title'>{messages('financial-account.key134')/*公式=*/}</div>
                {this.renderFormula()}
              </Col>
            </Row>
          </div>
        </Modal>
      </div>
    )
  }
}

CalculatorModal.propTypes = {
  visible: React.PropTypes.bool,
  onCancel: React.PropTypes.func.isRequired,
  onOk: React.PropTypes.func.isRequired,
  infoData: React.PropTypes.object,
  treeList: React.PropTypes.array,
  value: React.PropTypes.string
};

CalculatorModal.defaultProps = {
  visible: false
};

export default CalculatorModal;
